#include <lvgl.h>
#include <Arduino_GFX_Library.h>
#include "bsp_cst816.h"
#include "ui/ui.h"
#include "ip.h"
#include <string>
#include "ui/vars.h"

#include "time.h"

// #include <NTPClient.h>

#define EXAMPLE_PIN_NUM_LCD_SCLK 39
#define EXAMPLE_PIN_NUM_LCD_MOSI 38
#define EXAMPLE_PIN_NUM_LCD_MISO 40
#define EXAMPLE_PIN_NUM_LCD_DC 42
#define EXAMPLE_PIN_NUM_LCD_RST -1
#define EXAMPLE_PIN_NUM_LCD_CS 45
#define EXAMPLE_PIN_NUM_LCD_BL 1
#define EXAMPLE_PIN_NUM_TP_SDA 48
#define EXAMPLE_PIN_NUM_TP_SCL 47

#define LEDC_FREQ 5000
#define LEDC_TIMER_10_BIT 10

#define EXAMPLE_LCD_ROTATION 1
#define EXAMPLE_LCD_H_RES 240
#define EXAMPLE_LCD_V_RES 320


const char* ssid = "xiaohe";
const char* password = "23456789";

// WiFiUDP ntpUDP;
// NTPClient timeClient(ntpUDP, "pool.ntp.org", 28800); // 28800 是 UTC+8 的偏移量
// 定义一个变量来记录上次执行的时间
unsigned long lastUpdateTime = 0;

std::string time_str;
extern "C" const char *get_var_time_str() {
    return time_str.c_str();
}

extern "C" void set_var_time_str(const char *value) {
    time_str = value;
}


int32_t time_stamp;

extern "C" int32_t get_var_time_stamp() {
    return time_stamp;
}

extern "C" void set_var_time_stamp(int32_t value) {
    if(value>10000000)
    time_stamp = value;
}


Arduino_DataBus *bus = new Arduino_ESP32SPI(
  EXAMPLE_PIN_NUM_LCD_DC /* DC */, EXAMPLE_PIN_NUM_LCD_CS /* CS */,
  EXAMPLE_PIN_NUM_LCD_SCLK /* SCK */, EXAMPLE_PIN_NUM_LCD_MOSI /* MOSI */, EXAMPLE_PIN_NUM_LCD_MISO /* MISO */);

Arduino_GFX *gfx = new Arduino_ST7789(
  bus, EXAMPLE_PIN_NUM_LCD_RST /* RST */, EXAMPLE_LCD_ROTATION /* rotation */, true /* IPS */,
  EXAMPLE_LCD_H_RES /* width */, EXAMPLE_LCD_V_RES /* height */);

uint32_t screenWidth;
uint32_t screenHeight;
uint32_t bufSize;
lv_disp_draw_buf_t draw_buf;
lv_color_t *disp_draw_buf;
lv_disp_drv_t disp_drv;
uint32_t num = 0;

void my_disp_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) {
  lv_disp_flush_ready(disp_drv);
}

void my_touchpad_read(lv_indev_drv_t *indev_drv, lv_indev_data_t *data) {
  uint16_t touchpad_x;
  uint16_t touchpad_y;
  bsp_touch_read();
  if (bsp_touch_get_coordinates(&touchpad_x, &touchpad_y)) {
    data->point.x = touchpad_x;
    data->point.y = touchpad_y;
    data->state = LV_INDEV_STATE_PRESSED;
  } else {
    data->state = LV_INDEV_STATE_RELEASED;
  }
}

void setup() {
  Serial.begin(115200);
  Serial.println("Arduino_GFX LVGL_Arduino_v8 example ");

  if (!gfx->begin()) {
    Serial.println("gfx->begin() failed!");
  }
  gfx->fillScreen(BLACK);

#ifdef EXAMPLE_PIN_NUM_LCD_BL
  ledcAttach(EXAMPLE_PIN_NUM_LCD_BL, LEDC_FREQ, LEDC_TIMER_10_BIT);
  ledcWrite(EXAMPLE_PIN_NUM_LCD_BL, (1 << LEDC_TIMER_10_BIT) / 100 * 80);
#endif

  Wire.begin(EXAMPLE_PIN_NUM_TP_SDA, EXAMPLE_PIN_NUM_TP_SCL);
  bsp_touch_init(&Wire, gfx->getRotation(), gfx->width(), gfx->height());
  lv_init();

  screenWidth = gfx->width();
  screenHeight = gfx->height();
  bufSize = screenWidth * screenHeight;

  disp_draw_buf = (lv_color_t *)heap_caps_malloc(bufSize * 2, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
  if (!disp_draw_buf) {
    disp_draw_buf = (lv_color_t *)heap_caps_malloc(bufSize * 2, MALLOC_CAP_8BIT);
  }

  if (!disp_draw_buf) {
    Serial.println("LVGL disp_draw_buf allocate failed!");
  } else {
    lv_disp_draw_buf_init(&draw_buf, disp_draw_buf, NULL, bufSize);

    lv_disp_drv_init(&disp_drv);
    disp_drv.hor_res = screenWidth;
    disp_drv.ver_res = screenHeight;
    disp_drv.flush_cb = my_disp_flush;
    disp_drv.draw_buf = &draw_buf;
    disp_drv.direct_mode = true;

    lv_disp_drv_register(&disp_drv);

    static lv_indev_drv_t indev_drv;
    lv_indev_drv_init(&indev_drv);
    indev_drv.type = LV_INDEV_TYPE_POINTER;
    indev_drv.read_cb = my_touchpad_read;
    lv_indev_drv_register(&indev_drv);
  }

  Serial.println("Setup done");
  ui_init();

  // 连接WiFi
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nConnected to WiFi");
  //初始化网络时间戳
  set_var_time_stamp(getTimeStamp());
   // 初始化 NTP 客户端
  // timeClient.begin();
}

void time_show(){

//  timeClient.update(); // 更新 NTP 时间
//   String timedate = timeClient.getFormattedTime(); // 获取格式化的时间字符串

  // 将时间字符串存储到全局变量中
  // set_var_time_str(timedate.c_str());

  // 打印日期和时间
  // Serial.println("Current time: " + timedate);


  time_t rawTime = get_var_time_stamp();
    struct tm * timeinfo;
  timeinfo = localtime(&rawTime);
   // 手动调整时区为 UTC+8
  timeinfo->tm_hour = (timeinfo->tm_hour + 8) % 24;

  String timedate = String(timeinfo->tm_year + 1900) + "-" + String(timeinfo->tm_mon + 1) + "-" + String(timeinfo->tm_mday) + "\n" + String(timeinfo->tm_hour) + ":" + String(timeinfo->tm_min) + ":" + String(timeinfo->tm_sec);
  // 打印日期和时间
  Serial.print("年: ");
  Serial.print(timeinfo->tm_year + 1900); // tm_year是从1900年开始的年份，所以需要加1900
  Serial.print("-");
  Serial.print(timeinfo->tm_mon + 1); // tm_mon是从0开始的月份，所以需要加1
  Serial.print("-");
  Serial.print(timeinfo->tm_mday);
  Serial.print(" ");
  Serial.print(timeinfo->tm_hour);
  Serial.print(":");
  Serial.print(timeinfo->tm_min);
  Serial.print(":");
  Serial.println(timeinfo->tm_sec);
  set_var_time_str(timedate.c_str());
}

void loop() {
  lv_timer_handler();
  ui_tick();
  num++;
  // Serial.println(num);
  if(num==2000){
    // String myIP = getMyIP();
    set_var_time_stamp(getTimeStamp());

    // Serial.println("My IP address is: " + myIP);
    // String timedate = getTime();
    
 
    // Serial.println("Time " + timedate);
    // set_var_time_stamp_str(timedate.c_str());
    num=0;

  }

//  //每1000ms执行一次
//   if(millis()%100==0){
//     Serial.println("millis"+String(millis()));
//     set_var_time_stamp(get_var_time_stamp()+1);
//     time_show();
//   }

    // 每1000ms执行一次
  unsigned long currentTime = millis();
  if (currentTime - lastUpdateTime >= 1000) {
      Serial.println("millis: " + String(currentTime));
      set_var_time_stamp(get_var_time_stamp() + 1);
      time_show();
      lastUpdateTime = currentTime; // 更新上次执行的时间
  }

#if (LV_COLOR_16_SWAP != 0)
  gfx->draw16bitBeRGBBitmap(0, 0, (uint16_t *)disp_draw_buf, screenWidth, screenHeight);
#else
  gfx->draw16bitRGBBitmap(0, 0, (uint16_t *)disp_draw_buf, screenWidth, screenHeight);
#endif
  delay(5);
}